package com.btobtob.a.biz.user.config;


import com.btobtob.a.biz.user.commonjackson.ZonedDateTimeDeserializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

@Configuration
//@Primary
public class JacksonSerializerConfiguration implements WebMvcConfigurer {

//    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
//    private String pattern;
//    @Value("${spring.jackson.time-zone:GMT+8}")
//    private String timeZone;

    private static final String DEFAULT_ZONED_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSz";
    private static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
    private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
    private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss.SSS";
    private String ShangHaiZone = "GMT+8";


    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> cvt : converters) {
            if (cvt instanceof MappingJackson2HttpMessageConverter converter) {
                enhanceConvertor(converter);
            }
        }
    }

    private void enhanceConvertor(MappingJackson2HttpMessageConverter converter) {
        ObjectMapper objectMapper = converter.getObjectMapper();
//        objectMapper.setTimeZone(TimeZone.getTimeZone(ShangHaiZone));
//        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+0"));
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //关闭日期序列化为时间戳的功能
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //关闭序列化的时候没有为属性找到getter方法,报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //空值不序列化
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //序列化空对象不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //关闭反序列化的时候，没有找到属性的setter报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        //反序列化未知属性不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //自定义序列化：key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
        SimpleModule module = new SimpleModule();
//        module.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_ZONED_DATE_TIME_PATTERN)));
//        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_ZONED_DATE_TIME_PATTERN)));
//        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));
//        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));
//        module.addSerializer(Date.class, new DateSerializer(false,new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN)));
        //module.addSerializer(Long.class,ToStringSerializer.instance); // 会将mybatis-plus 分页返回的total也转成字符串导致flutter问题

        // 自定义序列化：long认为是雪花ID，转为string。
        module.addSerializer(Long.class, new JsonSerializer<Long>() {
            @Override
            public void serialize(Long value, JsonGenerator gen, SerializerProvider provider) throws IOException {
                String str = String.valueOf(value);
//                if (str.length()>=18) {// 自定义序列化：long长度超过18位则认为是雪花ID，转为string，否则为数字，
//                    gen.writeString(str);
//                }else {
//                    gen.writeNumber(value);
//                }
                gen.writeString(str);
            }
        });
        //自定义反序列化：key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
//        module.addDeserializer(ZonedDateTime.class, new ZonedDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_ZONED_DATE_TIME_PATTERN)));
//        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_ZONED_DATE_TIME_PATTERN)));
//        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));
//        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));
//        module.addDeserializer(Date.class, new DateDeserializers.DateDeserializer(){
//            @SneakyThrows
//            @Override
//            public Date deserialize(JsonParser p, DeserializationContext ctxt){
//                String text = p.getText().trim();
//                SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);
//                return sdf.parse(text);
//            }
//        });
        objectMapper.registerModule(module);
    }

}
